"""
WebSocket相关路由
"""

import asyncio
import json
import time
import logging
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
from services.net_service import net_manager
from services.serial_service import serial_manager
from utils.data_utils import format_received_data
from config import settings

# 配置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

router = APIRouter(tags=["WebSocket"])


@router.websocket("/ws/net/{connection_id}")
async def net_websocket_endpoint(websocket: WebSocket, connection_id: str):
    """网络WebSocket端点，用于实时数据传输(支持TCP和UDP)"""
    await websocket.accept()
    logger.info(f"WebSocket连接已建立: {connection_id}")

    # 记录最后接收数据的时间
    last_data_time = time.time()
    # 心跳间隔（秒）
    heartbeat_interval = 1.0  # 1秒
    # 检查数据的时间间隔
    check_data_interval = 0.1  # 100ms
    # 连接超时时间（秒）
    connection_timeout = settings.WEBSOCKET_TIMEOUT

    try:
        while True:
            current_time = time.time()

            # 检查连接是否存在
            connection = net_manager.get_connection(connection_id)
            if not connection:
                await websocket.send_text(
                    json.dumps(
                        {
                            "type": "error",
                            "message": "连接不存在",
                            "timestamp": current_time,
                        }
                    )
                )
                logger.warning(f"连接不存在: {connection_id}")
                break

            # 检查连接是否超时
            if current_time - last_data_time > connection_timeout:
                logger.warning(f"WebSocket连接超时: {connection_id}")
                break

            # 尝试读取网络数据
            data = await asyncio.to_thread(net_manager.read_data, connection_id)
            if data:
                formatted_data = format_received_data(data)
                await websocket.send_text(
                    json.dumps(
                        {
                            "type": "data",
                            "connection_id": connection_id,
                            "data": formatted_data["text"],
                            "hex_data": formatted_data["hex"],
                            "length": formatted_data["length"],
                            "timestamp": current_time,
                        }
                    )
                )
                logger.debug(f"网络接收数据: {formatted_data['text'][:50]}...")
                last_data_time = current_time
            else:
                # 每心跳间隔发送一次状态信息
                if current_time - last_data_time >= heartbeat_interval:
                    await websocket.send_text(
                        json.dumps(
                            {
                                "type": "heartbeat",
                                "data": {
                                    "connectionId": connection_id,
                                    "status": (
                                        "connected"
                                        if connection["connected"]
                                        else "disconnected"
                                    ),
                                    "protocol": connection["config"].get(
                                        "protocol", "tcp"
                                    ),
                                    "host": connection["config"].get("host", ""),
                                    "port": connection["config"].get("port", 0),
                                    "stats": connection["stats"],
                                },
                                "timestamp": current_time,
                            }
                        )
                    )
                    last_data_time = current_time

            # 等待一段时间再次检查
            await asyncio.sleep(check_data_interval)

    except WebSocketDisconnect:
        logger.info(f"WebSocket连接已断开: {connection_id}")
    except asyncio.CancelledError:
        logger.info(f"WebSocket任务已取消: {connection_id}")
    except Exception as e:
        logger.error(f"WebSocket错误: {str(e)}")
        try:
            await websocket.send_text(
                json.dumps(
                    {
                        "type": "error",
                        "message": f"WebSocket错误: {str(e)}",
                        "timestamp": time.time(),
                    }
                )
            )
        except Exception as send_error:
            logger.error(f"发送错误消息失败: {str(send_error)}")
    finally:
        # 清理资源
        logger.info(f"WebSocket资源已清理: {connection_id}")


@router.websocket("/ws/serial/{port:path}")
async def serial_websocket_endpoint(websocket: WebSocket, port: str):
    """串口WebSocket端点，用于实时数据传输"""
    await websocket.accept()

    try:
        while True:
            # 检查连接是否存在
            connection = serial_manager.get_connection(port)
            if not connection:
                await websocket.send_text(
                    json.dumps(
                        {
                            "type": "error",
                            "message": "串口连接不存在",
                            "timestamp": time.time(),
                        }
                    )
                )
                break

            # 尝试读取串口数据
            data = await asyncio.to_thread(serial_manager.read_data, port)
            if data:
                formatted_data = format_received_data(data)
                await websocket.send_text(
                    json.dumps(
                        {
                            "type": "data",
                            "port": port,
                            "data": formatted_data["text"],
                            "hex_data": formatted_data["hex"],
                            "length": formatted_data["length"],
                            "timestamp": time.time(),
                        }
                    )
                )
            else:
                # 发送心跳信息
                await websocket.send_text(
                    json.dumps(
                        {
                            "type": "heartbeat",
                            "port": port,
                            "connected": connection["connected"],
                            "stats": connection["stats"],
                            "timestamp": time.time(),
                        }
                    )
                )

            # 等待一段时间再次检查
            await asyncio.sleep(settings.WEBSOCKET_PING_INTERVAL)

    except WebSocketDisconnect:
        pass
    except Exception as e:
        try:
            await websocket.send_text(
                json.dumps(
                    {
                        "type": "error",
                        "message": f"WebSocket错误: {str(e)}",
                        "timestamp": time.time(),
                    }
                )
            )
        except:
            pass
